/*
 * $Id: ChfFile.java,v 1.6 2009/11/03 14:50:38 navdeep_mahajan Exp $
 * 
 * Copyright (C) 2008 General Electric Company. All Rights Reserved.
 * 
 * This software is the confidential and proprietary information of the General
 * Electric Company (GE). You shall not disclose this software and shall use it
 * only in accordance with the terms of the license agreement you entered into
 * with GE.
 * 
 * GE MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
 * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
 * NON-INFRINGEMENT. GE SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING, OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES.
 */
package com.ge.healthcare.autosc.processor.iptds.transaction;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.Vector;

import com.ge.healthcare.autosc.common.ASCLogger;
import com.ge.healthcare.autosc.common.dbLogger.StepLogger;
import com.ge.healthcare.autosc.common.util.ASCFileHandler;
import com.ge.healthcare.autosc.common.util.TimeFormatStandard;

/**
 * 
 * @author 212042946
 * 
 */
public class ChfFile extends Properties {
	public static final String TDF_KEY = "TDF";
	public static final String BATCH_MODE = "batch";
	public static final String SINGLE_MODE = "single";
	public static final String MODE = "MODE";
	public static final String PATHTOASC = "PATHTOASC";
	public static final String PATHFROMASC = "PATHFROMASC";
	public static final String ORIGINATINGUSN = "ORIGINATINGUSN";

	public static final long serialVersionUID = 0L;

	/*
	 * contains the items
	 */
	private Vector<ThfProperties> thf = new Vector<ThfProperties>();

	/*
	 * contains the CHF file name
	 */
	private File fName = null;
	// is the Chf valid
	boolean valid = true;
	// Invalid reason
	private StringBuffer invalidReason = new StringBuffer();
	// Start time for uploading chf file
	private Date startTime = null;
	// End time for uploading chf file
	private Date endTime = null;

	private ArrayList<String> logs = new ArrayList<String>();

	public ChfFile() {
		startTime = TimeFormatStandard.getNowMillis();
	}

	/**
	 * Clear this object. Includes superclass properties and 'thf'.
	 * 
	 */
	public void clear() {
		super.clear();
		thf.clear();
	}

	/**
	 * Load object from a CHF file.
	 * 
	 * precondition: Any previous contents is destroyed invariant:
	 * 
	 * @param chfName
	 *            Fully qualified path name of CHF file
	 * 
	 *            postconditions: Chf data available through accessors
	 */
	public void loadFile(String chfName) throws IOException {
		endTime = TimeFormatStandard.getNowMillis();
		loadFile(new File(chfName));
	}

	public void loadFile(File f) throws IOException {
		endTime = TimeFormatStandard.getNowMillis();
		clear();
		fName = f;

		if (f.exists()) {
			String r;
			String key, value;
			BufferedReader in = new BufferedReader(new InputStreamReader(
					new FileInputStream(f)));

			Properties p = this;
			for (r = in.readLine(); r != null; r = in.readLine()) {
				StringTokenizer st = new StringTokenizer(r, "=");
				if (st.hasMoreTokens() != true) {
					continue;
				}
				key = st.nextToken();
				key = key.trim();
				key = key.toUpperCase();
				if (st.hasMoreTokens() == true) {
					value = st.nextToken();
					value = value.trim();
					p.setProperty(key, value);
				} else if (key.startsWith("THF") && key.endsWith("{")) {
					if (p != this) {
						break;
					}
					p = new ThfProperties();
				} else if (key.equals("}")) {
					thf.addElement((ThfProperties) p);
					p = this;
				}
			}
			in.close();
		}
		Collections.sort(thf);
	}

	/**
	 * Move the chf to a new location
	 * 
	 * @param dest
	 *            full qualified destination path
	 * @return
	 */
	public boolean move(String dest) {
		boolean status = false;
		File destDir = new File(dest);
		// We only take directory
		if (!destDir.exists()) {
			if (destDir.mkdirs() == false) {
				ASCLogger.error("Unable to create directory " + dest);
			}
		}
		if (destDir.exists()) {
			File destFile = new File(destDir, fName.getName());
			if (ASCFileHandler.rename(fName, destFile)) {
				fName = destFile;
				status = true;
			}
		}
		return status;
	}

	/**
	 * Accessor for 'THF' Properties
	 * 
	 * @param name
	 *            Key for desire enumeration
	 * 
	 * @return Enumerations containing sorted THF Properties
	 */
	public Enumeration<ThfProperties> elements(String name) {
		if (name.compareToIgnoreCase(TDF_KEY) == 0) {
			return thf.elements();
		}
		return null;
	}

	/**
	 * Accessor for loaded filename
	 * 
	 * @return File object represented loaded file
	 */
	public File getFile() {
		return fName;
	}

	public String getFilename() {
		return fName.getName();
	}

	public String getFilePath() {
		return fName.getAbsolutePath();
	}

	public String getParent() {
		return fName.getParent();
	}

	public String getPathToAsc() {
		return this.getProperty(ChfFile.PATHTOASC);
	}

	public boolean isBatchMode() {
		return (ChfFile.BATCH_MODE.equalsIgnoreCase(this
				.getProperty(ChfFile.MODE)));
	}

	public boolean isLoaded() {
		return (fName != null) ? true : false;
	}

	public void validate(String usn) {
		String origUsn = this.getProperty(ChfFile.ORIGINATINGUSN);
		if ((usn == null) || !(origUsn.equalsIgnoreCase(usn))) {
			invalidReason.append("usn are not the same as.");
			invalidReason.append("{").append(ChfFile.ORIGINATINGUSN)
					.append("=").append(origUsn).append("}");
			invalidReason.append("{given usn=").append(usn).append("}");
			addLog(invalidReason.toString());
			valid = false;
		}

		if (valid == true) {
			String mode = this.getProperty(ChfFile.MODE);
			if ((mode == null)
					|| !(mode.equalsIgnoreCase("single") || mode
							.equalsIgnoreCase("batch"))) {
				invalidReason.append("Invalid CHF mode");
				addLog(invalidReason.toString());
				valid = false;
			}
		}

		if (valid == true) {
			if ((this.getProperty(ChfFile.PATHTOASC) == null)
					|| (this.getProperty(ChfFile.PATHFROMASC) == null)) {
				invalidReason.append(ChfFile.PATHTOASC).append(" and/or ")
						.append(ChfFile.PATHFROMASC);
				invalidReason.append(" is not defined");
				addLog(invalidReason.toString());
				valid = false;
			}
		}
	}

	public boolean isValid() {
		return valid;
	}

	public String getInvalidReason() {
		return invalidReason.toString();
	}

	public static void main(String[] a) throws Exception {
		int i;

		ChfFile cf = new ChfFile();

		/*
		 * parse the arguments
		 */
		for (i = 0; i < a.length; i++) {
			if (a[i].equals("-f")) {
				i++;
				if (i < a.length) {
					cf.loadFile(a[i]);
				}
			}
		}
		System.out.println(cf);
	}

	public Date getStartTime() {
		return startTime;
	}

	public void setStartTime(Date startTime) {
		this.startTime = startTime;
	}

	public Date getEndTime() {
		return endTime;
	}

	public void setEndTime(Date endTime) {
		this.endTime = endTime;
	}

	public void addLog(String log) {
		logs.add(log);
	}

	public void copyLogsToStepLogger() {
		if (logs.size() > 0) {
			for (String log : logs) {
				StepLogger.addStepLog(log);
			}
		}
		logs.clear();
	}

	public String toString() {
		StringBuffer b = new StringBuffer();
		b.append("CHF Properties:\n");
		Enumeration<?> propertyNames = this.propertyNames();
		while (propertyNames.hasMoreElements()) {
			String name = (String) propertyNames.nextElement();
			b.append("{").append(name).append("=").append(
					this.getProperty(name)).append("}");
		}
		b.append("\n");
		b.append("Number of THF: " + thf.size()).append("\n");
		Enumeration<ThfProperties> e = thf.elements();
		while (e.hasMoreElements()) {
			b.append("{").append("A THF PROPERTY");
			Properties pp = (Properties) e.nextElement();
			b.append(pp);
			b.append("}");
			b.append("\n");
		}
		return b.toString();
	}
}
